<?php

/* MyMeeting is an online meeting management software.
 * Copyright (C) 2009 Government Of Malaysia
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * @author: Abdullah Zainul Abidin, Nuhaa All Bakry
 *          Eavay Javay Barnad, Sarogini Muniyandi,Teow Jit Huan
 *
 *
 */

class AppController extends Controller {   
    /**
     * Define $components
     *
     */
    var $components = array('Auth','p28n','RequestHandler','Session');
    
    var $helpers = array('Html', 'Javascript','Session');
    /**
     * Define $uses
     *
     */
    var $uses = array('Committee','Log','User');

    var $dcommittee = null;
    
    var $permission =array();
    /**
     * Describe idFromShortName
     *
     * @param $shortname
     * @return null
     */
    function idFromShortName($shortname){
        $ddat=$this->Committee->getData(array('id'),array('short_name'=>$shortname));
        if(count($ddat)>1){
            $this->Session->setFlash(__('There appears to be more than 1 committee with that name'));
            $this->redirect(array('controller'=>'committees','action'=>'mainpage'));
        }
        elseif(count($ddat)==1){
            return $ddat[0]['Committee']['id'];
        }
        else{
            $this->Session->setFlash(__('Please select a valid committee'));
            $this->redirect(array('controller'=>'committees','action'=>'mainpage'));
        }
    }

    function writelog($class=null,$method=null,$msg=null) {
        $user = $this->Auth->user('id');
        // save to db
        if(isset($this->params['url']['url']) && $this->params['controller']!='ajaxes'){
            $curlog['user_id']=$user;
            $curlog['controller']=$this->params['controller'];
            $curlog['action']=$this->params['action'];
            if(isset($this->params['id'])) $curlog['targetid']=$this->params['id'];
            if(isset($this->params['pass']['0'])) $curlog['targetid']=$this->params['pass']['0'];
            $curlog['url']=$this->params['url']['url'];
            $curlog['timestamp']=date('Y-m-d H:i:s');
            $curlog['message']="[$class $method $user] $msg";
            $this->Log->create();
            $this->Log->save($curlog);
        }
        // save to debug.log
        if ($msg)
            $this->log("[$class $method $user] $msg", LOG_DEBUG);
        else
            if (isset($this->params['id']))
                $this->log("[$class $method $user] ".$this->params['controller']."/".$this->params['action']." for ".$this->params['id'], LOG_DEBUG);
            elseif (isset($this->params['pass']['0']))
                $this->log("[$class $method $user] ".$this->params['controller']."/".$this->params['action']." for ".$this->params['pass']['0'], LOG_DEBUG);
            else
                $this->log("[$class $method $user] ".$this->params['controller']."/".$this->params['action'], LOG_DEBUG);
    }

    /**
     * Describe beforeFilter
     *
     * @return null
     */
    function beforeFilter() {
        $this->set('show_sidemenu', 0);
        //to avoid login by the locked user 
        if(!empty($this->data['User']['username'])){
            $duser=$this->User->find('first',array('conditions'=>array('username'=>$this->data['User']['username'])));
            if(!empty($duser) && date('Y-m-d H:i:s',strtotime($duser['User']['locked']))>date('Y-m-d H:i:s')){
                $this->data['User']['password']=null;
            }
        }
        //$_SESSION['Message']['flash']['message'] = '';
        
        $this->Auth->loginAction=array('controller'=>'users','action'=>'login');
        $this->Auth->loginRedirect=array('controller'=>'committees','action'=>'mainpage');
        $this->Auth->logoutRedirect=array('controller'=>'users','action'=>'login');
        $this->Auth->loginError=__('Invalid username or password',true);
        $this->Auth->authorize='controller';
        $this->Auth->allow(array('changeInvite','captcha','forgotpass','forgotuser','hash1',
                'install','database','dircheck','language','syssettings','success','addUser','help','ical','cal'));
        
        if($this->Auth->user('id')){
            $this->{$this->modelClass}->curUser=$this->Auth->user('id');
            $this->writelog(get_class($this),__FUNCTION__);

            $this->committee_permission();

            // set the page user will be redirected to after captcha & changing password
            if (!$this->Session->check('lastvisitedpage')) {
                if(!in_array($this->params['action'],array('haschangedpassword','logout','forcechangepassword','login')))
                $lastvisitedpage = $this->params['url']['url'] ;
                $this->Session->write('lastvisitedpage',$lastvisitedpage);
            }
            
            // check captcha
            if ($this->Session->check('securitycode') && $this->params['url']['url'] != 'logout' && $this->params['url']['url'] != 'users/captcha') {

                if ($this->data['User']['captcha'] == $this->Session->read('securitycode')) {
                    $this->Session->write('passcaptcha',1);
                    $this->Session->write('redirected',0);
                    $this->Session->delete('securitycode');
                    $this->writelog(get_class($this),__FUNCTION__,'Correct captcha value: '.$this->data['User']['captcha']);
                } else {
                    $this->Session->SetFlash(__('You have entered wrong code',true));
                    $this->Session->write('passcaptcha',0);
                    $this->Session->write('redirected',1);
                    $this->Session->delete('securitycode');

                    $this->Session->write('login_username',$this->data['User']['username']);
                    $this->Session->write('login_captcha',$this->data['User']['captcha']);

                    $this->writelog(get_class($this),__FUNCTION__,'Incorrect captcha value: '.$this->data['User']['captcha']);
                    $this->redirect(array('controller'=>'users','action'=>'login',));
                }

            } else {
                $this->Session->write('passcaptcha',1);
            }

            // check if user has changed their default password
            if ($this->Session->read('passcaptcha') &&  !$this->Session->read('redirected')) {
                // if user not coming from root url
                if (!$this->Session->check('haschanged') && $this->params['url']['url'] != 'users/haschangedpassword') {

                    if (!$this->Session->check('lastvisitedpage')) {
                        // set the page user will be redirected to after changing password
                        $lastvisitedpage = $this->params['url']['url'];
                        $this->Session->write('lastvisitedpage',$lastvisitedpage);
                    }
                    $this->writelog(get_class($this),__FUNCTION__,"lastvisitedpage: ".$this->params['url']['url']);

                    if ($this->params['controller']."/".$this->params['action'] != 'users/forcechangepassword' && $this->params['controller']."/".$this->params['action'] != 'users/logout') {
                        $this->writelog(get_class($this),__FUNCTION__,"Redirecting to haschangedpassword from ".$this->Session->read('lastvisitedpage'));
                        $this->redirect(array('controller'=>'users','action'=>'haschangedpassword'));
                    }
                }
                if ($this->Session->read('haschanged') == 'N') {
                    if ($this->params['controller']."/".$this->params['action'] != 'users/forcechangepassword' && $this->params['controller']."/".$this->params['action'] != 'users/logout') {
                        $this->writelog(get_class($this),__FUNCTION__,"Redirecting to forcechangepassword from ".$this->params['controller']."/".$this->params['action']);
                        $this->redirect(array('controller'=>'users','action'=>'forcechangepassword'));
                    }
                }
            }
            $this->permit();
        }
        // set page title
        $this->pageTitle = __(ucfirst($this->params['controller']),true);
        
        

    }
    
    //find the committee and the permission in the committee
    function committee_permission(){
        if (count($this->params['pass']) && is_array($this->params)) {
            $dcommittee=$this->Committee->findByShortName($this->params['pass'][0]);
            $this->params['committee'] = $dcommittee['Committee']['short_name'];
        }  
        // set dcommittee
        if (isset($this->params['committee'])) {
            $this->dcommittee=$this->Session->read('committee');
            if(!$this->Session->check('committee') || $this->dcommittee['Committee']['short_name']!=$this->params['committee']){
                //if the session don't have committee or the committee change
                $this->Session->write('committee',$this->Committee->findByShortName($this->params['committee']));
                $this->dcommittee=$this->Session->read('committee');
                $this->Session->write('permission',$this->getPermission($this->dcommittee['Committee']['id'],$this->Auth->user('id')));
            }
   
            if(!$this->Session->check('permission')){
                $this->Session->write('permission',$this->getPermission($this->dcommittee['Committee']['id'],$this->Auth->user('id')));
            }
            $this->permission=$this->Session->read('permission');
            $this->Committee->contain(array('Todo','Item'));
            $this->set('dcommittee',$this->dcommittee);
            if($this->params['action']=='index'){
                $this->set('permission',$this->permission);
            }
        }
    }

    //determine the page are permit or not
    function permit(){
            //only for superuser
            $su_url = array('committees/add',
                'users/index','users/add','users/view','users/edit',
                'titles/index','titles/add','titles/view','titles/edit',
                'protocols/index','protocols/add','protocols/edit',
                'roles/index','roles/add','roles/edit',
                'systemtodos/index','systemtodos/add','systemtodos/edit',
                'minutetypes/index','minutetypes/add','minutetypes/edit','minutetypes/view',
                'schemes/index','schemes/add','schemes/edit','schemes/view',
                'settings/edit','settings/logo','logs/index','logs/report'
            );
            //for all user
            $all_url=array('committees/mainpage','/','profile','users/changepassword','users/haschangedpassword','calendar','help','logout','login','committees/find','committees/add','getmultidata','users/forcechangepassword');
            $all_controller=array('ajaxes','hashes');
            
            $action=array('view'=>'View','edit'=>'Edit','add'=>'Create','index'=>'sum','delete'=>'Delete');
        
            //current user not the superuser and not browse the page for all user
            if($this->Auth->user('superuser')==0 && !in_array($this->params['controller'],$all_controller) && !in_array($this->params['url']['url'],$all_url) && !($this->params['action']=='view' && in_array($this->params['controller'],array('memberships','groups')))){
                //add role for committee
                if(!empty($this->params['url']['url']) && $this->params['url']['url']!='roles/add' && $this->params['controller']=='roles' && $this->params['action']=='add' && empty($this->dcommittee)){
                }elseif($this->params['controller']=='committees' && $this->params['action']=='add' && strpos($this->Session->read('history'),'addsubcomm/')){
                    //add subcommittee
                }elseif(in_array($this->params['controller'].'/'.$this->params['action'],$su_url)){
                    //the current user browser the page which just for superuser
                    $this->notpermit();
                }elseif(in_array($this->params['controller'].'/'.$this->params['action'],array('templates/edit','templates/view')) && empty($this->dcommittee)){
                    //the current user browser the page which just for superuser
                    $this->notpermit();
                }elseif(!empty($this->dcommittee) && $this->Session->read('permission')==array()){
                    //non-member can't enter the committee
                    $this->notpermit();
                }elseif(in_array($this->params['controller'],array('memberships','groups')) && $this->params['action']=='index'){
                }elseif(empty($this->permission['Wfmodel']['Edit']) && $this->params['controller']=='wfmodels'){
                    //wfmodel permission
                    $this->notpermit();
                }elseif($this->params['controller']=='templates' && $this->params['action']=='guide'){
                    if(!strpos($this->Session->read('history'),'emplates/')){
                    //template guide not from template index page
                        $this->notpermit();
                    }
                }elseif($this->params['controller']=='templates' && $this->params['action']=='reset' && empty($this->permission['Template']['Edit'])){
                    //template rest
                    $this->notpermit();
                }elseif($this->params['controller']=='committees' && $this->params['action']=='addsubcomm' && empty($this->permission['Committee']['Create'])){
                    //add sub committee
                    $this->notpermit();
                }elseif($this->params['controller']=='committees' && array_key_exists($this->params['action'],$action) && empty($this->permission['Committee'][$action[$this->params['action']]])){
                    //edit committee
                    $this->notpermit();
                }elseif(in_array($this->params['controller'],array('templates','Templates','announcements','committeetodos','groups','memberships'))){
                    if(empty($this->dcommittee) ||(array_key_exists($this->params['action'],$action) && empty($this->permission[inflector::singularize(ucfirst($this->params['controller']))][$action[$this->params['action']]]))){
                        $this->notpermit();
                    }
                }elseif(in_array($this->params['controller'],array('meetings','items')) && $this->params['action']=='add' && empty($this->permission[inflector::singularize(ucfirst($this->params['controller']))]['Create'])){
                    //add page
                    $this->notpermit();
                }
            }
    }
    
    //if the user is not allowed to view this page
    function notpermit(){
        $this->Session->SetFlash(__('You have no permission to enter /'.$this->params['url']['url'],true));
        if(!$this->Session->check('history') || $this->Session->read('history')==$this->params['url']['url'] ||in_array($this->Session->read('history'),array('getmultidata'))){
            $this->redirect('/');
        }else{
            $this->redirect('/'.$this->Session->read('history'));
        }
    }
    
    /**
     * Describe beforeRender
     *
     * @return null
     */
    function beforeRender(){
        /* dont display adminmenu for these */
        $no_adminmenu = array('committees/mainpage','committees/add','committees/find',
            'users/index','users/add','users/view','users/edit','users/profile','users/changepassword','users/forcechangepassword',
            'users/captcha',
            'titles/index','titles/add','titles/edit',
            'protocols/index','protocols/add','protocols/edit',
            'roles/index','roles/add','roles/edit','systemtodos/index','systemtodos/add','systemtodos/edit',
            'templates/index','templates/add','templates/edit','templates/view','templates/config',
            'minutetypes/index','minutetypes/add','minutetypes/edit','minutetypes/view','minutetypes/guide',
            'schemes/index','schemes/add','schemes/edit','schemes/view',
            'settings/edit','settings/logo','logs/index','logs/report',
            'hashes/hash','calendar','committees/calendar','installers/install','installers/install1','installers/install2','installers/install3','committees/help'
        );
        
        /* display sidemenu for these */
        $show_sidemenu = array('committees/add',
            'users/index','users/add','users/view','users/edit',
            'titles/index','titles/add','titles/view','titles/edit',
            'protocols/index','protocols/add','protocols/edit',
            'roles/index','roles/add','roles/edit',
            'systemtodos/index','systemtodos/add','systemtodos/edit',
            'templates/index','templates/add','templates/edit','templates/view',
            'minutetypes/index','minutetypes/add','minutetypes/edit','minutetypes/view',
            'schemes/index','schemes/add','schemes/edit','schemes/view',
            'settings/edit','settings/logo','logs/index','logs/report'
        );

        if($this->Auth->user()){
            $this->set('auth_user',$this->Auth->user());
            
            //$this->set('registeredCommittee',$this->Committee->registeredCommitteeList($this->Auth->user('id')));
            // show adminmenu?
            if (!in_array($this->params['controller'].'/'.$this->params['action'],$no_adminmenu) )
                $this->set('show_adminmenu', 1);
            else
                $this->set('show_adminmenu', 0);
            // show sidemenu?
            if (in_array($this->params['controller'].'/'.$this->params['action'],$show_sidemenu) ) {
                $this->set('show_sidemenu', 1);
                if (isset($this->params['committee']) && $this->params['controller']=='templates') {$this->set('show_sidemenu', 0); }
            } else {
                $this->set('show_sidemenu', 0);
            }
        }

        $this->set('img_path',$this->getLogo());

        // get version number
        $this->set('version',$this->_getVersionNumber());
        
        // use this setting if it's ajax request
        if ($this->RequestHandler->isAjax()) {
            parent::__construct();
            Configure::write('debug', 1); // dont want debug in ajax returned html
            $this->disableCache();
            $this->layout='empty';
        }
        if(!empty($this->params['url']['url'])){
            $this->Session->write('history',$this->params['url']['url']);
        }
    }

    function _getVersionNumber() {

        $dfile = APP . 'VERSION.txt';
        $handle = fopen($dfile, "r");
        $contents = fread($handle, filesize($dfile));
        fclose($handle);
        return $contents;
    }
    /**
     * Describe isAuthorized
     *
     * @return null
     */
    function isAuthorized(){
        return true;
        if($this->Auth->user('superuser') || $this->params['controller']=='ajaxes'){
            /* All superusers and ajax controllers can do anything */
            return true;
        }

        $allowedactions=array('index','alert');
        if(in_array($this->params['action'],$allowedactions)) return true;
        $item=null;
        $committee=null;
        $committee_roles=null;
        if(isset($this->params['id'])) $item=$this->params['id'];
        if(isset($this->params['committee'])) {
            $committee_id=$this->idFromShortName($this->params['committee']);
            $committee_roles = $this->Committee->userData($this->Auth->user('id'),$committee_id);
        }
        $permission=$this->{Inflector::classify($this->params['controller'])}->isAuthorized($this->Auth->user('id'),$this->params['action'],$item,$committee_id,$committee_roles);
        return $permission;
    }

/*
    function generateAuth($user_id,$committee_id,$models) {
        // get the rules from wfmodel
        $wfmodel = ClassRegistry::init('Wfmodel','model');
        $rules = $wfmodel->getRules($committee_id,$models);
        $authlist = array();
        foreach ($rules as $rule) {
            $actions = Set::extract($rule,'/Wfmodel/@*'); // get all keynames
            $model = $rule['Wfmodel']['model'];
            foreach ($actions[0] as $action)
                $authlist['Authlist'][$model][$action] = $rule['Wfmodel'][$action];
        }
        
        // get current user role and groups for this committee
        $userdata=$this->Committee->userData($user_id,$committee_id);
        $authlist['Authlist']['user'] = $userdata;
        return $authlist;
    }*/
    
    //get committee permission
    function getPermission($committee_id,$user_id){
        $this->Committee->Membership->recursive=-1;
        $membership=$this->Committee->Membership->find('first',array('conditions'=>array('Membership.committee_id'=>$committee_id,'Membership.user_id'=>$user_id)));
        if(empty($membership)){
            return array();
        }elseif(!empty($membership['Membership']['role_id'])){
            $role_id=$membership['Membership']['role_id'];
        }else{
            $role_id=2;
        }
        $this->loadModel('Wfmodel');
        $wfmodels=$this->Wfmodel->committee_role($committee_id,$role_id);
        $this->Committee->Membership->recursive=1;
        foreach($wfmodels as $w=>$wfmodel){
            $wfmodels[$w]['sum']=array_sum($wfmodel);
        }
        return $wfmodels;
    }
    
    //find permission for each data(in index page)
    function fixupauth($data,$model){
        //$not_permit=array_diff(array('View','Edit','Delete'),array_keys(array_filter($this->permission[$model])));
        foreach($data as $did=>$ddata){
            if($model=='Meeting'){
                $data[$did]['auth']=$this->meetingPermission($ddata['Meeting']['id']);
                $data[$did]['auth']['Minute']=$this->minutePermission(in_array('minutes approved',set::extract($ddata,'Notification.{n}.type')));
                $field_key=array('secretariat','edit','delete','attendance','minute');
            }elseif($model=='Item'){
                $data[$did]['auth']=$this->itemPermission($ddata);
                $field_key=array('edit','delete');
            }else{
                $data[$did]['auth']=$this->permission[$model];
            }
        }
        
        // for crud -- give a empty place for the entry which have no permission (but have permission on other entry)
        foreach($field_key as $fkey){
            $f[$fkey]=array_sum(set::extract($data,'{n}.auth.'.Inflector::camelize($fkey)));
        }
        foreach($data as $did=>$ddata){
            foreach($field_key as $fkey){
                $data[$did]['auth'][$fkey]=$f[$fkey]>0?1:0;
            }
        }
        return $data;
    }
    
    function meetingPermission($meeting_id){
        $permitted=$this->permission['Meeting'];
        $Attendance=$this->permission['Attendance']['View'];
        $attendance=$this->Meeting->Attendance->find('first',array('fields'=>array('attended','attend_as'),'conditions'=>array('Attendance.meeting_id'=>$meeting_id,'Attendance.user_id'=>$this->Auth->user('id'))));
        if(!empty($attendance)){
            $Attendance=$this->permission['Attendance -Invited']['View'];
            if($attendance['Attendance']['attend_as']==1){
                $permitted['Secretariat']=1;
            }elseif($attendance['Attendance']['attended']==1){
                $permitted=$this->permission['Meeting -Attended'];
            }else{
                $permitted=$this->permission['Meeting -Invited'];
            }
        }
        $permitted['Attendance']=$Attendance;
        return $permitted;
    }
    
    //if user was implementor in any decision for item:permission['Item -Involve'];else:permission['Item']
    function itemPermission($data){
        $permitted=$this->permission['Item'];
        $decision=set::extract($data,'Decision.{n}.id');
        if(!empty($decision)){
            if($this->Committee->Item->Decision->DecisionsUser->find('count',array('conditions'=>array('user_id'=>$this->Auth->user('id'),'decision_id'=>$decision)))){
                $permitted=$this->permission['Item -Involve'];
            }else{
                $group=array_unique(set::extract($this->Committee->Item->Decision->DecisionsGroup->find('all',array('conditions'=>array('decision_id'=>$decision))),'{n}.DecisionsGroup.group_id'));
                if( !empty($group) && $this->Committee->Group->UsersGroup->find('count',array('conditions'=>array('group_id'=>$group,'user_id'=>$this->Auth->user('id'))))){
                    $permitted=$this->permission['Item -Involve'];
                }
            }
            $permitted['Delete']=0;
        }
        return $permitted;
    }
    
    //if minute was approved:permission['Minute -Approved mode']['View'];else:permission['Minute -Draft mode']['View']
    function minutePermission($notified){
        if($notified==1){
              return $this->permission['Minute -Approved mode']['View'];
        }else{
            return $this->permission['Minute -Draft mode']['View'];
        }
    }
    
    
    //if decision was accepted: permission['Decision -Accepted'];if user is implementor:['Decision -Assigned'];else:permission['Decision']
    function decisionPermission($data){
        $permitted=$this->permission['Decision'];
        if($data['Decision']['approved']){
            $permitted=$this->permission['Decision -Accepted'];
        }elseif(in_array($this->Auth->user('id'),Set::extract($data['User'],'{n}.id'))){
            $permitted=$this->permission['Decision -Assigned'];
        }else{
            $group=Set::extract($data['Group'],'{n}.id');
            if(!empty($group) && $this->Committee->Group->UsersGroup->find('count',array('conditions'=>array('group_id'=>$group,'user_id'=>$this->Auth->user('id'))))){
                $permitted=$this->permission['Decision -Assigned'];
            }
        }
        return $permitted;
    }
    

    /**
     * Describe getLogo
     *
     * @return string path to logo
     */
    function getLogo() {

        $logo_uploaded = WWW_ROOT . 'img' . DS . 'logo';
        $found = array();
        $folder = new Folder($logo_uploaded);
        $found = $folder->find();

        if (count($found)) {
            return 'logo'. DS . $found[0];
        } else {
            return 'mymeetingv3.png';
        }
    }
}
?>
